package fun.yegang.config;


import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
import org.springframework.security.oauth2.client.web.HttpSessionOAuth2AuthorizedClientRepository;
import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;

import static fun.yegang.global.Constants.IGNORE_AUTHENTICATION_RESOURCES;

@Configuration
@EnableWebSecurity
//@EnableMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
@Slf4j
public class CustomSecurityConfiguration {

    @Value("${security.enabled}")
    private boolean securityEnabled;
    @Value("${security.same-site.enabled}")
    private boolean securitySameSiteEnabled;
    @Value("${security.keycloak.enabled:false}")
    private boolean keyCloakEnabled;
    @Value("${security.oauth2.enabled:false}")
    private boolean oauth2Enabled;
    @Value("${security.oauth2.logout.url:}")
    private String oauth2LogoutUrl;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        if (!securitySameSiteEnabled) {
            http.headers(AbstractHttpConfigurer::disable);
        } else {
            http.headers(header -> header.frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin));
        }

        if (securityEnabled) {
            CookieCsrfTokenRepository csrfTokenRepository = new CookieCsrfTokenRepository();
            csrfTokenRepository.setCookieCustomizer(cookie -> cookie.secure(true)
                    .maxAge(86400));
            http.csrf(csrf -> csrf.ignoringRequestMatchers(IGNORE_AUTHENTICATION_RESOURCES)
                    .csrfTokenRepository(csrfTokenRepository));
            return http.build();
        }

        // 使用其他方式认证时关闭 csrf
        http.csrf(AbstractHttpConfigurer::disable);

        if (keyCloakEnabled || oauth2Enabled) {
            http.authorizeHttpRequests(a -> a
                            .requestMatchers(IGNORE_AUTHENTICATION_RESOURCES)
                            .permitAll()
                            .anyRequest()
                            .authenticated())
                    .oauth2Login(Customizer.withDefaults());
            if (StringUtils.isNotBlank(oauth2LogoutUrl)) {
                http.logout(r -> r.logoutSuccessUrl(oauth2LogoutUrl));
            }
            log.info("{} enabled ...", keyCloakEnabled ? "Keycloak" : "Oauth2");
            return http.build();
        }

        log.info("Security CSRF disabled ...");
        return http.build();
    }
}


